/*
Copyright 2010-2011 CumulusCloud
http://cumuluscloud.cc

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cumulusCloud.folderdb;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import cumulusCloud.folderdb.converter.Converter;

public class FolderDB<T> implements FolderDBInterface<T> {
	private static Logger logger = Logger.getLogger(FolderDB.class.getName());
	
	private File folder;
	private Converter<T> converter;
	
	@Override
	public boolean deleteObject(String id) {
		validateId(id);
		String filename = folder.getAbsolutePath() + File.separatorChar + id;
		return new File(filename).delete();
	}

	@Override
	public List<T> getAllObjects() {
		List<T> result = new ArrayList<T>();
		
		for (File next: folder.listFiles()) {
			try {
				T obj = converter.toObject(new FileInputStream(next));
				result.add(obj);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
				continue;
			}
		}
		return result;
	}

	@Override
	public T getObject(String id) {
		validateId(id);
		String filename = folder.getAbsolutePath() + File.separatorChar + id;
		
		FileInputStream in = null;
		try {
			in = new FileInputStream(filename);
			return converter.toObject(in);
		} catch (FileNotFoundException e) {
			logger.log(Level.FINE, "Could not find the object with id {0}", id);
		} finally {
			try {
				in.close();
			} catch (Exception e) {
			}
		}
		
		return null;
	}

	@Override
	public boolean init(String folderpath, Converter<T> converter) {
		this.converter = converter;
		
		// Create the path if not exists
		folder = new File(folderpath);
		if (!folder.exists()) {
			return folder.mkdirs();
		}
		
		return true;
	}
	
	@Override
	public boolean saveObject(T object) {
		String id = converter.getId(object);
		validateId(id);
		String filename = folder.getAbsolutePath() + File.separatorChar + id;
		OutputStream out = null;
		try {
			out = new FileOutputStream(filename);
			converter.toSerial(object, out);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return false;
		} finally {
			try {
				out.close();
			} catch (Exception e) {
			}
		}
		
		return true;
	}

	private void validateId(String id) throws RuntimeException {
		if ( 	(id == null) ||
				(!id.matches("^[\\w]+$"))
				) {
			throw new RuntimeException("Id not valid");
		}
	}
}
